#include "TvLayout.h"
#include "led.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QLinkedList>
#include <QtGui>
#include <QDebug>

TvLayout::TvLayout() :
	LedWidth(0),
	LedHeight(0),
	startLed(QPoint(50,50)),
	disabled(QList<int>()),
	CW(true),
	margins(50)
{
	ScreenResolution.setWidth(QApplication::desktop()->width());
	ScreenResolution.setHeight(QApplication::desktop()->height());
}

bool TvLayout::generateLedsTest(QList<Led *> *list){
	LedWidth = 20;
	LedHeight = 10;
	startLed = QPoint(0,0);
	CW = true;
	return generateLeds(list);
}

bool TvLayout::generateLeds(QList<Led *> *list){
	if(!list) return false;
	if(LedWidth==0 || LedHeight==0) return false;
	for(int i=0;i<list->size();i++) delete list->at(i);
	list->clear();
	int count = LedWidth*2 + (LedHeight-2)*2;

	for(int i=0;i<count;i++){
		if(isDisabled(i)) continue;
		Led* led = new Led(countPos(i));
		led->setRect(countRect(i));
		list->push_back(led);
	}
	return true;
}

bool TvLayout::isDisabled(int index){
	for(int i=0;i<disabled.size();i++){
		if(disabled.at(i) == index) return true;
	}
	return false;
}

QRect TvLayout::countRect(int index){
	QPoint coord = indexToCoord(index);
	int dw = ScreenResolution.width() / LedWidth;
	int dh = ScreenResolution.height() / LedHeight;
	return QRect(dw*coord.x(),dh*coord.y(),dw,dh);
}

QPoint TvLayout::countPos(int index){
	QPoint coord = indexToCoord(index);
	return countPos(coord.x(),coord.y());
}

QPoint TvLayout::countPos(int x, int y){
	int dw = ( ScreenResolution.width() - 2*margins ) / (LedWidth - 1);
	int dh = ( ScreenResolution.height() - 2*margins ) / (LedHeight - 1);
	return QPoint(margins+x*dw, margins+y*dh);
}

QPoint TvLayout::indexToCoord(int index){
	int count = LedWidth*2 + (LedHeight-2)*2;
	QLinkedList<QPoint> cells;
	// fill list with existing leds (CW)
	int x=0,y=0;
	cells.push_back(QPoint(0,0));
	for(int i=1;i<count;i++){
		if(i<LedWidth){
			x++;
		}
		else if(i>=LedWidth && i<LedWidth+LedHeight-1){
			y++;
		}
		else if(i>=LedWidth+LedHeight-1 && i<2*LedWidth+LedHeight-2){
			x--;
		}
		else{
			y--;
		}
		cells.push_back(QPoint(x,y));
	}

	// count position of index
	QLinkedListIterator<QPoint> it(cells);
	bool find = false;
	while(it.hasNext()){
		if(it.peekNext().x() == startLed.x() && it.peekNext().y() == startLed.y()){
			it.next();
			find = true;
			break;
		}
		it.next();
	}
	if(!find) return QPoint(-1,-1);

	QPoint ret = startLed;

	if(!CW) it.previous();
	for(int i=0;i<index;i++){
		if(CW){
			if(!it.hasNext()) {it.toFront(); it.next(); ret = cells.first(); }
			else ret = it.next();
		}
		else{
			if(!it.hasPrevious()) {it.toBack(); it.previous(); ret = cells.last(); }
			else ret = it.previous();
		}
	}

	return ret;
}

int TvLayout::pointToIndex(QPoint point){
	int count = LedWidth*2 + (LedHeight-2)*2;
	for(int i=0;i<count;i++){
		if(countRect(i).contains(point)){
			return i;
		}
	}
	return -1;
}

void TvLayout::enableLed(QPoint point, bool state){
	int index = pointToIndex(point);
	if(index == -1) return;
	// disable
	if(!state){
		for(int i=0;i<disabled.length();i++){
			if(disabled.at(i) == index) return;
		}
		disabled.push_back(index);
	}

	// enable
	else{
		for(int i=0;i<disabled.length();i++){
			if(disabled.at(i) == index){
				disabled.removeAt(i);
				return;
			}
		}
	}
}

void TvLayout::setStart(int index){
	startLed = indexToCoord(index);
}

void TvLayout::setSide(bool cw){
	CW = cw;
}
